package main

import (
	"errors"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/rpc"
	"sync"
)

type PutArgs struct {
	Key   string
	Value string
}
type PutApply struct{}

type GetArgs struct {
	Key string
}
type GetApply struct {
	Key   string
	Value string
}

type KVServer struct {
	mu    sync.Mutex
	cache map[string]string
}

func (t *KVServer) Put(args *PutArgs, reply *PutApply) error {
	t.mu.Lock()
	defer t.mu.Unlock()
	t.cache[args.Key] = args.Value
	return nil
}

func (t *KVServer) Get(args *GetArgs, reply *GetApply) error {
	t.mu.Lock()
	defer t.mu.Unlock()
	if v, ok := t.cache[args.Key]; ok {
		reply.Key = args.Key
		reply.Value = v
	} else {
		return errors.New("can't find this key")
	}
	return nil
}

func connect() *rpc.Client {
	serverAddress := "127.0.0.1"
	client, err := rpc.DialHTTP("tcp", serverAddress+":1234")
	if err != nil {

	}
	return client
}

func put(v string) {
	client := connect()
	args := PutArgs{Key: "monkey", Value: v}
	err := client.Call("KVServer.Put", args, &PutArgs{})
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("Put %s:%s\n", args.Key, args.Value)

}

func get() {
	client := connect()
	args := GetArgs{Key: "monkey"}
	apply := &GetApply{}
	err := client.Call("KVServer.Get", args, apply)
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("Get %s:%s\n", apply.Key, apply.Value)
}

func runserver() {
	cache := make(map[string]string)
	KVs := KVServer{cache: cache}
	rpc.Register(&KVs)
	rpc.HandleHTTP()
	l, e := net.Listen("tcp", ":1234")
	if e != nil {
		log.Fatal("listen error:", e)
	}
	go http.Serve(l, nil)
}

func requestServer() {
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		put("ying")
		wg.Done()
	}()
	go func() {
		put("xuew")
		wg.Done()
	}()
	wg.Wait()
	get()
}

func main() {
	runserver()
	requestServer()
}
